using System;
using System.IO;
using System.Security;
using System.Threading;
using System.Security.Permissions;

public static class Program {
   public static void Main() {
      // Show that the method works just fine
      AttemptAccess("Default context");

      // Change the thread's execution context 
      // to disallow all file access
      new FileIOPermission(PermissionState.Unrestricted).Deny();

      // Show that the method no longer works due
      // to a change in the execution context
      AttemptAccess("No file permissions");

      ECFlowing();
      ECFlowingSuppressed();

      // Capture this thread's current execution context
      ExecutionContext ec = ExecutionContext.Capture();

      // Change the thread's execution context 
      // to allow file access
      SecurityPermission.RevertDeny();

      // Show that the method works just fine
      AttemptAccess("Default context again");

      ECCaptureAndRun(ec);
   }

   private static void ECFlowing() {
      // Initialize a delegate variable to refer 
      // to the method we want to call asynchronously
      WaitCallback wc = AttemptAccess;

      // Use a thread pool thread to attempt access
      // EndInvoke returns when thread pool thread returns to pool
      wc.EndInvoke(wc.BeginInvoke("ECFlowing", null, null));
   }

   private static void ECFlowingSuppressed() {
      // Initialize a delegate variable to refer 
      // to the method we want to call asynchronously
      WaitCallback wc = AttemptAccess;

      // Temporarily tell the CLR not to flow this 
      // thread's execution context to helper threads
      using (AsyncFlowControl afc = ExecutionContext.SuppressFlow()) {
         wc.EndInvoke(wc.BeginInvoke("ECFlowingSuppressed", null, null));
      }
   }

   private static void ECCaptureAndRun(ExecutionContext ec) {
      // Call AttemptAccess using the 
      // previously-captured execution context
      ExecutionContext.Run(ec, AttemptAccess, 
         "ECCaptureAndRun with Run");
   }

   private static void AttemptAccess(Object test) {
      // Assume this method fails
      Boolean success = false;
      try {
         // Try to get the file's attributes
         File.GetAttributes(@"C:\ReadMe.txt");

         // If we got the attributes, method succeeded
         success = true;
      }
      catch (SecurityException) {
         // Method failed due to insufficient security 
         // on thread's execution context
      }

      // Show whether the attempted access succeeded or failed
      Console.WriteLine("{0}: {1}", test, success);
   }
}
